home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / gs24src.zip / ZFILE.C < prev    next >
C/C++ Source or Header  |  1992-03-06  |  16KB  |  538 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* zfile.c */
  21. /* Non-I/O file operators for Ghostscript */
  22. #include "memory_.h"
  23. #include "string_.h"
  24. #include "ghost.h"
  25. #include "gp.h"
  26. #include "errors.h"
  27. #include "oper.h"
  28. #include "alloc.h"
  29. #include "estack.h"            /* for filenameforall */
  30. #include "iutil.h"
  31. #include "save.h"            /* for restore */
  32. #include "stream.h"
  33. #include "file.h"            /* must come after stream.h */
  34. #include "store.h"
  35.  
  36. /* Forward references */
  37. int lib_file_open(P6(byte *, uint, byte *, uint, uint *, ref *));
  38. int file_open(P5(byte *, uint, char *, ref *, stream **));
  39. int file_close(P2(ref *, stream *));
  40. private int open_std_file(P3(os_ptr, char *, os_ptr));
  41. /* In zfileio.c */
  42. ref *zget_current_file(P0());
  43.  
  44. /* Imported from gs.c */
  45. extern char **gs_lib_paths;        /* search path list, */
  46.                     /* terminated by a null pointer */
  47.  
  48. /* The chain of all open files.  We need this only */
  49. /* so that we can do the right thing for restore (and GC someday). */
  50. private ref all_files;            /* t_file */
  51. #define file_list all_files.value.pfile
  52.  
  53. /* File buffer sizes.  For real files, this is arbitrary, */
  54. /* since the C library does its own buffering in addition. */
  55. /* stdout and stderr use smaller buffers, */
  56. /* on the assumption that they are usually not real files. */
  57. /* The buffer size for type 1 encrypted files is NOT arbitrary: */
  58. /* it must be at most 512. */
  59. #define buffer_size 512
  60.  
  61. /* Standard file objects: */
  62. /* 0 is stdin, 1 is stdout, 2 is stderr, 3 is lineedit, 4 is statementedit */
  63. #define num_std_files 5
  64. stream invalid_file_entry;
  65. private byte
  66. #define stdin_buf_size 1
  67.     stdin_buf[stdin_buf_size],
  68. #define stdout_buf_size 128
  69.     stdout_buf[stdout_buf_size],
  70. #define stderr_buf_size 128
  71.     stderr_buf[stderr_buf_size],
  72. #define lineedit_buf_size 160
  73.     lineedit_buf[lineedit_buf_size];
  74. /* statementedit is equivalent to lineedit for now */
  75. stream std_files[num_std_files];
  76. private char *std_file_names[num_std_files] =
  77.    {    "%stdin",
  78.     "%stdout",
  79.     "%stderr",
  80.     "%lineedit",
  81.     "%statementedit"
  82.    };
  83. private int std_file_attrs[num_std_files] =
  84.    {    a_read+a_execute,
  85.     a_write+a_execute,
  86.     a_write+a_execute,
  87.     a_read+a_execute,
  88.     a_read+a_execute
  89.    };
  90.  
  91. /* Initialize the file table */
  92. private void
  93. zfile_init()
  94. {    /* Create files for stdin, stdout, and stderr. */
  95.     /****** stdin IS NOT IMPLEMENTED PROPERLY ******/
  96.     /* Note that we use gs_out instead of stdout. */
  97.     sread_file(&std_files[0], stdin, stdin_buf, stdin_buf_size);
  98.     std_files[0].can_close = 0;
  99.     swrite_file(&std_files[1], gs_out, stdout_buf, stdout_buf_size);
  100.     std_files[1].can_close = 0;
  101.     swrite_file(&std_files[2], stderr, stderr_buf, stderr_buf_size);
  102.     std_files[2].can_close = 0;
  103.     make_tav(&all_files, t_file, 0, pfile, (stream *)0);
  104.     s_disable(&invalid_file_entry);
  105. }
  106.  
  107. /* file */
  108. int
  109. zfile(register os_ptr op)
  110. {    char file_access[3];
  111.     ref fname;
  112.     int code;
  113.     stream *s;
  114.     fname = op[-1];
  115.     check_type(fname, t_string);
  116.     check_type(*op, t_string);
  117.     switch ( r_size(op) )
  118.        {
  119. /******
  120.     case 2:
  121.         if ( op->value.bytes[1] != '+' )
  122.             return e_invalidfileaccess;
  123.         file_access[1] = '+';
  124.         file_access[2] = 0;
  125.         break;
  126.  ******/
  127.     case 1:
  128.         file_access[1] = 0;
  129.         break;
  130.     default:
  131.         return e_invalidfileaccess;
  132.        }
  133.     switch ( *op->value.bytes )
  134.        {
  135.     case 'r': case 'w': /****** case 'a': ******/
  136.         break;
  137.     default:
  138.         return e_invalidfileaccess;
  139.        }
  140.     file_access[0] = *op->value.bytes;
  141.     code = open_std_file(op - 1, file_access, op - 1);
  142.     switch ( code )
  143.        {
  144.     case 0:                /* successful open */
  145.         pop(1);
  146.     default:            /* unsuccessful open */
  147.         return code;
  148.     case e_undefinedfilename:    /* not a %file */
  149.         ;
  150.        }
  151.     code = file_open(fname.value.bytes, r_size(&fname),
  152.              file_access, op - 1, &s);
  153.     if ( code >= 0 ) pop(1);
  154.     return code;
  155. }
  156.  
  157. /* closefile */
  158. int
  159. zclosefile(register os_ptr op)
  160. {    stream *s;
  161.     int code;
  162.     check_file(s, op);
  163.     if ( s->can_close == 0 )
  164.         return e_invalidaccess;    /* can't close std file */
  165.     if ( (code = file_close(op, s)) >= 0 )
  166.        {    /* If we just closed the file from which the interpreter */
  167.         /* is reading, zap it on the exec stack. */
  168.         ref *fp = zget_current_file();
  169.         if ( fp != 0 && fptr(fp) == fptr(op) )
  170.             /* A null would confuse the estack parser.... */
  171.             make_tasv(fp, t_array, a_executable+a_execute, 0, refs, (ref *)0);
  172.         pop(1);
  173.        }
  174.     return code;
  175. }
  176.  
  177. /* ------ Level 2 extensions ------ */
  178.  
  179. /* deletefile */
  180. int
  181. zdeletefile(register os_ptr op)
  182. {    char *str;
  183.     int stat;
  184.     check_read_type(*op, t_string);
  185.     str = ref_to_string(op, "deletefile");
  186.     if ( str == 0 ) return e_VMerror;
  187.     stat = unlink(str);
  188.     alloc_free(str, r_size(op) + 1, 1, "deletefile");
  189.     if ( stat != 0 ) return e_ioerror;
  190.     pop(1);
  191.     return 0;
  192. }
  193.  
  194. /* filenameforall */
  195. private int file_continue(P1(os_ptr));
  196. private int i_file_continue;
  197. int
  198. zfilenameforall(register os_ptr op)
  199. {    file_enum *pfen;
  200.     check_write_type(*op, t_string);
  201.     check_proc(op[-1]);
  202.     check_read_type(op[-2], t_string);
  203.     /* Push a mark, the pattern, the scratch string, the enumerator, */
  204.     /* and the procedure, and invoke the continuation. */
  205.     check_estack(7);
  206.     pfen = gp_enumerate_files_init((char *)op[-2].value.bytes, r_size(op - 2), alloc, alloc_free);
  207.     if ( pfen == 0 ) return e_VMerror;
  208.     mark_estack(es_for);
  209.     *++esp = op[-2];
  210.     *++esp = *op;
  211.     ++esp;
  212.     make_tasv(esp, t_string, a_read+a_execute+a_executable, 0,
  213.           bytes, (byte *)pfen);
  214.     *++esp = op[-1];
  215.     pop(3);  op -= 3;
  216.     return file_continue(op);
  217. }
  218. /* Continuation operator for enumerating files */
  219. private int
  220. file_continue(register os_ptr op)
  221. {    es_ptr pscratch = esp - 2;
  222.     file_enum *pfen = (file_enum *)esp[-1].value.bytes;
  223.     uint len = r_size(pscratch);
  224.     uint code = gp_enumerate_files_next(pfen, (char *)pscratch->value.bytes, len);
  225.     if ( code == ~(uint)0 )        /* all done */
  226.        {    gp_enumerate_files_close(pfen);
  227.         esp -= 4;        /* pop mark, scatch, pfen, proc */
  228.         return o_pop_estack;
  229.        }
  230.     else if ( code > len )        /* overran string */
  231.        {    gp_enumerate_files_close(pfen);
  232.         return e_rangecheck;
  233.        }
  234.     else if ( !string_match(pscratch->value.bytes, code,
  235.                 pscratch[-1].value.bytes,
  236.                 r_size(&pscratch[-1]),
  237.                 gp_file_names_ignore_case)
  238.         )
  239.        {    /* Enumerator was too liberal, ignore this one. */
  240.         push_op_estack(file_continue, i_file_continue);    /* come again */
  241.         return o_push_estack;
  242.        }
  243.     else
  244.        {    push(1);
  245.         ref_assign(op, pscratch);
  246.         r_set_size(op, code);
  247.         push_op_estack(file_continue, i_file_continue);    /* come again */
  248.         *++esp = pscratch[2];    /* proc */
  249.         return o_push_estack;
  250.        }
  251. }
  252.  
  253. /* renamefile */
  254. int
  255. zrenamefile(register os_ptr op)
  256. {    char *str1 = 0, *str2 = 0;
  257.     check_read_type(*op, t_string);
  258.     check_read_type(op[-1], t_string);
  259.     str1 = ref_to_string(op - 1, "renamefile(from)");
  260.     str2 = ref_to_string(op, "renamefile(to)");
  261.     if ( str1 != 0 && str2 != 0 && rename(str1, str2) == 0 )
  262.        {    pop(2);
  263.        }
  264.     if ( str1 != 0 )
  265.         alloc_free(str1, r_size(op - 1) + 1, 1, "renamefile(from)");
  266.     if ( str2 != 0 )
  267.         alloc_free(str2, r_size(op) + 1, 1, "renamefile(to)");
  268.     return 0;
  269. }    
  270.  
  271. /* ------ Ghostscript extensions ------ */
  272.  
  273. /* findlibfile */
  274. int
  275. zfindlibfile(register os_ptr op)
  276. {    int code;
  277. #define maxclen 200
  278.     byte cname[maxclen];
  279.     uint clen;
  280.     check_type(*op, t_string);
  281.     code = open_std_file(op, "r", op - 1);
  282.     switch ( code )
  283.        {
  284.     case 0:                /* successful open */
  285.         push(1);
  286.         make_bool(op, 1);
  287.     default:            /* unsuccessful open */
  288.         return code;
  289.     case e_undefinedfilename:    /* not a %file */
  290.         ;
  291.        }
  292.     code = lib_file_open(op->value.bytes, r_size(op), cname, maxclen,
  293.                  &clen, op);
  294.     if ( code >= 0 )
  295.        {    byte *cstr = (byte *)alloc(clen, 1, "findlibfile");
  296.         if ( cstr == 0 ) return e_VMerror;
  297.         memcpy(cstr, cname, clen);
  298.         push(2);
  299.         op[-1] = op[-2];
  300.         make_tasv(op - 2, t_string, a_all, clen, bytes, cstr);
  301.         make_bool(op, 1);
  302.        }
  303.     else
  304.        {    push(1);
  305.         make_bool(op, 0);
  306.        }
  307.     return 0;
  308. }
  309.  
  310. /* ------ Initialization procedure ------ */
  311.  
  312. op_def zfile_op_defs[] = {
  313.     {"1closefile", zclosefile},
  314.     {"1deletefile", zdeletefile},
  315.     {"2file", zfile},
  316.     {"3filenameforall", zfilenameforall},
  317.     {"1findlibfile", zfindlibfile},
  318.     {"2renamefile", zrenamefile},
  319.         /* Internal operators */
  320.     {"0%file_continue", file_continue, &i_file_continue},
  321.     op_def_end(zfile_init)
  322. };
  323.  
  324. /* ------ Non-operator routines ------ */
  325.  
  326. /* Open a file, using the search paths if necessary. */
  327. /* The startup code calls this to open the initialization file gs_init.ps. */
  328. int
  329. lib_file_open(byte *fname, uint len, byte *cname, uint max_clen,
  330.   uint *pclen, ref *pfile)
  331. {    int code;
  332.     char **ppath;
  333.     stream *s;
  334.     code = file_open(fname, len, "r", pfile, &s);
  335.     if ( code >= 0 )
  336.        {    memcpy(cname, fname, len);
  337.         *pclen = len;
  338.         return code;
  339.        }
  340.     if ( gp_file_name_is_absolute((char *)fname, len) )
  341.         return e_undefinedfilename;
  342.     /* Go through the list of search paths */
  343.     for ( ppath = gs_lib_paths; *ppath != 0; ppath++ )
  344.        {    char *path = *ppath;
  345.         for ( ; ; )
  346.            {    /* Find the end of the next path */
  347.             char *npath = path;
  348.             uint plen;
  349.             char *cstr;
  350.             uint clen;
  351.             while ( *npath != 0 && *npath != gp_file_name_list_separator )
  352.                 npath++;
  353.             plen = npath - path;
  354.             cstr = gp_file_name_concat_string(path, plen,
  355.                               (char *)fname, len);
  356.             /* Concatenate the prefix, combiner, and file name. */
  357.             clen = plen + strlen(cstr) + len;
  358.             if ( clen <= max_clen )    /* otherwise punt */
  359.                {    memcpy(cname, (byte *)path, plen);
  360.                 strcpy((char *)cname + plen, cstr);
  361.                 memcpy(cname + clen - len, fname, len);
  362.                 *pclen = clen;
  363.                 code = file_open(cname, clen, "r",
  364.                          pfile, &s);
  365.                 if ( code >= 0 ) return code;
  366.                }
  367.             /****** NYI ******/
  368.             if ( !*npath ) break;
  369.             path = npath + 1;
  370.            }
  371.        }
  372.     return code;
  373. }
  374.  
  375. /* Open a file and create a file object. */
  376. /* Return 0 if successful, error code if not. */
  377. /* If fname==0, set up the file entry, stream, and buffer, */
  378. /* but don't open an OS file or initialize the stream. */
  379. /* The filter routines also use this. */
  380. int
  381. file_open(byte *fname, uint len, char *file_access, ref *pfile, stream **ps)
  382. {    byte *buffer;
  383.     stream *s;
  384.     int code;
  385.     if ( len >= buffer_size )
  386.         return e_limitcheck;    /* we copy the file name into the buffer */
  387.     /* Allocate the stream first, since it persists */
  388.     /* even after the file has been closed. */
  389.     s = (stream *)alloc(1, sizeof(stream), "file_open(stream)");
  390.     if ( s == 0 ) return e_VMerror;
  391.     /* Allocate the buffer. */
  392.     buffer = (byte *)alloc(buffer_size, 1, "file_open(buffer)");
  393.     /* Set the close procedure in case we have to free the file */
  394.     /* before actually initializing the stream. */
  395.     s->procs.close = s_std_close;
  396.     if ( buffer == 0 )
  397.        {    alloc_free((char *)s, 1, sizeof(stream), "file_open(stream)");
  398.         return e_VMerror;
  399.        }
  400.     if ( fname != 0 )
  401.        {    /* Copy the name (so we can terminate it with a zero byte.) */
  402.         char *file_name = (char *)buffer;
  403.         FILE *file;
  404.         memcpy(file_name, fname, len);
  405.         file_name[len] = 0;        /* terminate string */
  406.         /* Open the file. */
  407.         file = fopen(file_name, file_access);
  408.         code = e_undefinedfilename;
  409.         if ( file == 0 )
  410.            {    alloc_free((char *)buffer, buffer_size, 1, "file_open(buffer)");
  411.             alloc_free((char *)s, 1, sizeof(stream), "file_open(stream)");
  412.             return code;
  413.            }
  414.         /* Set up the stream. */
  415.         if ( *file_access == 'r' )    /* reading */
  416.             sread_file(s, file, buffer, buffer_size);
  417.         else
  418.             swrite_file(s, file, buffer, buffer_size);
  419.        }
  420.     else                /* save the buffer and size */
  421.        {    s->cbuf = buffer;
  422.         s->bsize = s->cbsize = buffer_size;
  423.        }
  424.     s->can_close = 1;
  425.     s->strm_is_temp = 0;        /* not a temp stream */
  426.     if ( file_list != 0 )
  427.         file_list->prev = s;
  428.     s->next = file_list;
  429.     s->prev = 0;
  430.     file_list = s;
  431.     make_file(pfile,
  432.         (*file_access == 'r' ? a_read+a_execute : a_write+a_execute),
  433.         s);
  434.     *ps = s;
  435.     return 0;
  436. }
  437.  
  438. /* Free a stream and its buffer. */
  439. /* Free the stream and buffer in the reverse of the order */
  440. /* in which they were created, and hope for LIFO storage behavior. */
  441. void
  442. file_free_stream(register stream *s)
  443. {    alloc_free((char *)s->cbuf, s->cbsize, 1,
  444.            "file_free_stream(buffer)");
  445.     alloc_free((char *)s, 1, sizeof(stream),
  446.            "file_free_stream(stream)");
  447. }
  448.  
  449. /* Close a file.  The interpreter calls this when */
  450. /* it reaches the end of an executable file. */
  451. int
  452. file_close(ref *fp /* t_file */, stream *s)
  453. {    switch ( s->can_close )
  454.        {
  455.     case 0:                /* can't close std files, ignore */
  456.         break;
  457.     case -1:            /* ignore on statement/lineedit */
  458.         sclose(s);
  459.         s_disable(s);
  460.         break;
  461.     default:            /* ordinary or filter file */
  462.        {    char *stemp = (s->strm_is_temp ? (char *)s->strm : 0);
  463.         /* Save the links before freeing the stream. */
  464.         stream *sprev = s->prev, *snext = s->next;
  465.         if ( sclose(s) ) return e_ioerror;
  466.         s_disable(s);
  467.         file_free_stream(s);
  468.         if ( stemp != 0 )
  469.             alloc_free(stemp, 1, sizeof(stream),
  470.                    "file_close(sub-stream)");
  471.         /* Unlink the file from the list of all files. */
  472.         if ( sprev != 0 ) sprev->next = snext;
  473.         else file_list = snext;
  474.         if ( snext != 0 ) snext->prev = sprev;
  475.        }
  476.        }
  477.     return 0;
  478. }
  479.  
  480. /* ------ Internal routines ------ */
  481.  
  482. /* If a file name refers to one of the standard %files, */
  483. /* 'open' the file and return 0 or an error code, otherwise */
  484. /* return e_undefinedfilename. */
  485. private int
  486. open_std_file(os_ptr pfname, char *file_access, os_ptr pfile)
  487. {    int i;
  488.     for ( i = 0; i < num_std_files; i++ )
  489.       if ( !bytes_compare(pfname->value.bytes, r_size(pfname),
  490.                   (byte *)std_file_names[i],
  491.                   strlen(std_file_names[i]))
  492.         )
  493.        {    /* This is a standard file */
  494.         int attrs = (*file_access == 'r' ? a_read+a_execute : a_write+a_execute);
  495.         stream *s = &std_files[i];
  496.         if ( attrs != std_file_attrs[i] )
  497.             return e_invalidaccess;
  498.         make_file(pfile, attrs, s);
  499.         /* If this is %lineedit or %statementedit, */
  500.         /* read a line now. */
  501.         switch ( i )
  502.            {
  503.         case 3: case 4:
  504.            {    uint count;
  505.             int code = zreadline_stdin(lineedit_buf,
  506.                 lineedit_buf_size, &count);
  507.             if ( code < 0 ) return code;
  508.             sread_string(s, lineedit_buf, count);
  509.             s->can_close = -1;
  510.             return 0;
  511.            }
  512.            }
  513.         return 0;
  514.        }
  515.     return e_undefinedfilename;
  516. }
  517.  
  518. /* Close inaccessible files just before a restore, */
  519. /* or all files just before exiting. */
  520. void
  521. file_restore(alloc_save *save)
  522. {    while ( file_list != 0 &&
  523.         (save == 0 || alloc_is_since_save((char *)file_list, save))
  524.           )
  525.        {    stream *s = file_list;
  526.         if ( s->can_close > 0 )    /* ignore std & buffered files */
  527.            {    sclose(s);
  528.            }
  529.         file_list = s->next;
  530.         if ( s->next != 0 ) s->next->prev = s->prev;
  531.         s_disable(s);
  532.        }
  533. }
  534. void
  535. file_close_all()
  536. {    file_restore((alloc_save *)0);
  537. }
  538.